/*
 * ehdr.c
 *
 *  Created on: Sep 9, 2012
 *      Author: aortegag
 */

#include <stdlib.h>
#include <string.h>
#include "ehdr.h"
#include "common.h"
#include "logging.h"

elf_code_t read_elf_header(FILE *fd, Elf64_Ehdr *ehdr) {

	fseek(fd, 0, SEEK_SET);

	fread(ehdr, sizeof(Elf64_Ehdr), 1, fd);

	// Read the ELF identification.
	if (ehdr->e_ident[0] != ELFMAG0 || ehdr->e_ident[1] != ELFMAG1
			|| ehdr->e_ident[2] != ELFMAG2 || ehdr->e_ident[3] != ELFMAG3)
		return ELF_EHDR_MAGIC_NUMBER_ERROR;

	if (ehdr->e_ident[EI_CLASS] == ELFCLASSNONE)
		return ELF_EHDR_FILE_CLASS_ERROR;

	if (ehdr->e_ident[EI_DATA] == ELFDATANONE)
		return ELF_EHDR_DATA_ENCODING_ERROR;

	if (ehdr->e_ident[EI_VERSION] == EV_NONE)
		return ELF_EHDR_EIDENT_VERSION_ERROR;

	if (ehdr->e_version == EV_NONE)
		return ELF_EHDR_VERSION_ERROR;

	return ELF_SUCCESS;
}


/**
 *  \brief Pretty prints the ELF Header.
 *
 *  \note This function assumes an ELF header has been stored
 *  in the Elf structure.
 */
void	pretty_print_ehdr(const Elf64_Ehdr *ehdr)
{
	if(!ehdr){
		LOG_WARN("Invalid ELF Header.\n");
		return;
	}
	LOG_INFO("ELF Header:\n");
	LOG_INFO("===================================="\
					"=========================================\n");
	LOG_INFO("  Magic number:\t\t\t%02x %02x %02x %02x \n",\
			ehdr->e_ident[EI_MAG0], ehdr->e_ident[EI_MAG1],\
			ehdr->e_ident[EI_MAG2], ehdr->e_ident[EI_MAG3] );

	LOG_INFO("  Class:\t\t\t%s\n",\
			(ehdr->e_ident[EI_CLASS]==ELFCLASS64)?\
					STR(ELFCLASS64) : STR(ELFCLASS32));

	LOG_INFO("  Data encoding:\t\t%s\n",\
			(ehdr->e_ident[EI_DATA]==ELFDATA2LSB)?\
					"2's complement values, little endian.":\
					"2's complement values, big endian");

	LOG_INFO("  OS/ABI:\t\t\t%s\n", elf_os_abi(ehdr->e_ident[EI_OSABI]));

	LOG_INFO("  ABI Version:\t\t\t%d\n",ehdr->e_ident[EI_ABIVERSION]);

	LOG_INFO("  Machine (e_ident):\t\t%s\n",\
			( (ehdr->e_ident[EI_CLASS]==ELFCLASS64) && \
			  (ehdr->e_ident[EI_DATA]==ELFDATA2LSB) )?\
					 "Intel 64 bit architecture" : "Unknown architecture");

	LOG_INFO("  ELF Type:\t\t\t%s\n", elf_type(ehdr->e_type));

	LOG_INFO("  Machine (e_type):\t\t%s\n",machine_type(ehdr->e_machine));
	LOG_INFO("  Version:\t\t\t%#x\n", ehdr->e_version);
	LOG_INFO("  Entry point address:\t\t%#08x\n", (unsigned int)ehdr->e_entry);
	LOG_INFO("  Program headers offset:\t%d (%#08x) bytes\n",(unsigned int)ehdr->e_phoff,(unsigned int)(ehdr->e_phoff));
	LOG_INFO("  Section headers offset:\t%d (%#08x) bytes\n",(unsigned int)ehdr->e_shoff,(unsigned int)(ehdr->e_shoff));
	LOG_INFO("  Flags:\t\t\t%#08x\n",ehdr->e_flags);
	LOG_INFO("  Size of this ELF Header:\t%d (%#08x) bytes\n",ehdr->e_ehsize,ehdr->e_ehsize);
	LOG_INFO("  Size of Program Header entry:\t%02d (%#08x) bytes\n",ehdr->e_phentsize,ehdr->e_phentsize);
	LOG_INFO("  Number of Program Headers:\t%02d (%#08x) bytes\n",ehdr->e_phnum,ehdr->e_phnum);
	LOG_INFO("  Size of Section Header entry:\t%02d (%#08x) bytes\n",ehdr->e_shentsize,ehdr->e_shentsize);
	LOG_INFO("  Number of Program Headers:\t%02d (%#08x) bytes\n",ehdr->e_shnum,ehdr->e_shnum);
	LOG_INFO("===================================="\
				"=========================================\n");
}
